/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 * 
 *      http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package net.phoenix.repository.iterator;

import java.sql.SQLException;
import java.util.Collection;
import java.util.Iterator;
import java.util.Vector;

import javax.jcr.Node;
import javax.jcr.RepositoryException;

import net.phoenix.repository.BasicNode;
import net.phoenix.repository.JdbcSession;
import net.phoenix.repository.RepositoryRuntimeException;
import net.phoenix.repository.dao.NodeTableCountDao;
import net.phoenix.repository.dao.NodeTableQueryDao;
import net.phoenix.repository.data.NodeData;

/**
 * @author lixf
 * 
 */
public class ChildNodeIterator extends AbstractNodeIterator {
	private String name;
	private long pageSize;
	private long size;
	private Iterator<Node> nodes;
	private boolean recursive = false;
	private JdbcSession session;
	private String nodeId;

	public ChildNodeIterator(JdbcSession session, String nodeId) {
		this(session, nodeId, null);
	}

	public ChildNodeIterator(JdbcSession session, String nodeId, String name) {
		this(session, nodeId, name, false);
	}

	public ChildNodeIterator(JdbcSession session, String nodeId, String name,
			boolean recursive) {
		this.session = session;
		this.nodeId = nodeId;
		this.name = name;
		this.pageSize = 20;
		this.size = -1;
		this.nodes = null;
		this.recursive = recursive;
	}

	/**
	 * getSize
	 * 
	 * @return long
	 */
	public long getSize() {
		if (this.size >= 0)
			return this.size;

		NodeTableCountDao dao = session.getDao(NodeTableCountDao.class);
		try {
			if (name == null) {
				size = dao.countByParent(nodeId);
			} else if (recursive) {
				size = dao.countByParentRecursively(nodeId, name);
			} else {
				size = dao.countByParent(nodeId, name);
			}
		} catch (SQLException ex) {
			throw new RepositoryRuntimeException(ex);
		}

		return this.size;

	}

	/**
	 * nextNode
	 * 
	 * @return Node
	 * @todo Implement this net.phoenix.repository.NodeIterator method
	 */
	public Node nextNode() {
		if ((this.nodes == null) || (!this.nodes.hasNext()))
			try {
				this.populateNodes();
			} catch (RepositoryException e) {
				throw new RepositoryRuntimeException(e);
			}
		this.position++;
		return (Node) this.nodes.next();

	}

	private Iterator<Node> populateNodes() throws RepositoryException {
		final Collection<Node> nodes = new Vector<Node>((int) this.pageSize);
		NodeTableQueryDao dao = (NodeTableQueryDao) session
				.getDao(NodeTableQueryDao.class);
		NodeData[] data = null;
		try {
			if (name == null) {
				data = dao.findByParent(nodeId, position, pageSize);
			} else if (recursive) {
				data = dao.findByParentRecursively(nodeId, name, position,
						pageSize);

			} else {
				data = dao.findByParent(nodeId, name, position, pageSize);
			}
		} catch (SQLException ex) {
			throw new RepositoryException(ex);
		}
		for (int i = 0; i < data.length; i++) {
			BasicNode node = new BasicNode(session, data[i]);
			nodes.add(node);
		}
		ChildNodeIterator.this.nodes = nodes.iterator();

		return this.nodes;

	}

	public void setFetchSize(long size) {
		this.pageSize = size;
	}

}
